package com.lz.ovuola.repository.mysql;

import java.io.Serializable;

import javax.persistence.EntityManager;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.jpa.repository.support.QueryDslJpaRepository;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import org.springframework.data.querydsl.QueryDslUtils;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

public class MyDynamicRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable>
		extends JpaRepositoryFactoryBean<R, T, I> {

	protected RepositoryFactorySupport createRepositoryFactory(
			EntityManager entityManager) {
		return new MyDynamicRepositoryFactory(entityManager);
	}

	private static class MyDynamicRepositoryFactory<T, I extends Serializable>
			extends JpaRepositoryFactory {
		private EntityManager entityManager;

		public MyDynamicRepositoryFactory(EntityManager entityManager) {
			super(entityManager);
			this.entityManager = entityManager;
		}

		protected Object getTargetRepository(RepositoryMetadata metadata) {
			Class<?> repositoryInterface = metadata.getRepositoryInterface();
			JpaEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata
					.getDomainType());
			if (isQueryDslExecutor(repositoryInterface)) {
				return new QueryDslJpaRepository(entityInformation,
						entityManager);
			} else {
				return new MyDynamicRepositoryImpl(entityInformation,
						entityManager); // custom
				// implementation
			}
		}

		private boolean isQueryDslExecutor(Class<?> repositoryInterface) {
			return QueryDslUtils.QUERY_DSL_PRESENT
					&& QueryDslPredicateExecutor.class
							.isAssignableFrom(repositoryInterface);
		}

		protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
			// The RepositoryMetadata can be safely ignored, it is used by the
			// JpaRepositoryFactory
			// to check for QueryDslJpaRepository's which is out of scope.
			return MyDynamicRepositoryImpl.class;
		}
	}
}